package org.come.socket;

import com.gl.util.ServerUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.come.until.AESUtil;
import org.come.until.CreateTextUtil;
import org.come.until.Util;

import java.math.BigDecimal;
import java.net.NetworkInterface;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.concurrent.TimeUnit;

public class GameClient {
	//TODO 客户端版本号 对应服务端配置文件两端不一致则不允许登录
	public static String VERSION = "version230508";
	public static String BT = "大话西游Ⅱ经典版";
	public static String atid;
	public static String userid;
	public static int lianhua = 0;
	public static Channel channel;
	private NioEventLoopGroup workGroup = new NioEventLoopGroup();
//	private Channel channel;
	private Bootstrap bootstrap;
	public static String[] potAndIpStrings;
	// 私密钥匙
	private static String privateStr;

	/** zrikka 2020-0414 */
	public static String username;
	public static String userpasw;
	public static String ip;// netty ip
	public static int port;// netty 端口
	private String serverType;// 服务器类型version230508
	public static String payurl;
	/******/

	/** Mac地址 */
	public static String Mac;

	/** 断线重连信息 */
	public static String DXCL = null;
	public static BigDecimal tempreId = null;

	/** zrikka 2020-0414 */
	public GameClient() {
		ip = ServerUtil.IP;
		port = ServerUtil.PORT;
	}
	public GameClient(String ip ,int port) {
		GameClient.ip = ip;
		GameClient.port = port;

	}


	public static String getPrivateStr() {
		return privateStr;
	}

	public static void setPrivateStr(String privateStr) {
		GameClient.privateStr = privateStr;
	}
	/**
	 public static void main(String[] args) throws Exception {
	 String str = AESUtil.AESJDKDncode(CreateTextUtil.getContent("resource/other/opacity-inif.pat"),
	 ">LA~h4FNKPMJW077jxO");
	 privateStr = AESUtil.AESJDKDncode(CreateTextUtil.getContent("resource/other/opacity-selfinif.pat"), str);
	 //system.out.println(AESUtil.AESJDKDncode(CreateTextUtil.getContent("resource/other/init.txt"), privateStr));
	 }
	 */

	public void start() {
		try {
			bootstrap = new Bootstrap();
			bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);// 0拷贝
			bootstrap.group(workGroup).channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE, true)
					.handler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel socketChannel) throws Exception {
							ChannelPipeline p = socketChannel.pipeline();
							// 以("\n")为结尾分割的 解码器
							p.addLast("framer",
									new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter()));
							// 字符串解码和编码
							p.addLast("decoder", new StringDecoder(Charset.forName("utf-8")));
							p.addLast("encoder", new StringEncoder(Charset.forName("utf-8")));
							p.addLast(new IdleStateHandler(0, 30, 0, TimeUnit.SECONDS));
							p.addLast(new GameClientHandler(GameClient.this));
						}
					});
			bootstrap.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT);
			bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
			doConnect();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	// 初始化次数
	int a = 0;

	protected void doConnect() throws Exception {
		if (channel != null && channel.isActive()) {
			return;
		}
		SendMessageUntil.gameServerKey = ip + "|" + port;
		ChannelFuture future = bootstrap.connect(ip, port);
		future.addListener(new ChannelFutureListener() {
			@Override
			public void operationComplete(ChannelFuture futureListener) throws Exception {
				if (futureListener.isSuccess()) {
					// 重置次数
					a = 0;
					channel = futureListener.channel();
					/** zrikka 2020 0414 **/
//                    if ("login".equals(serverType)) {
//                        return;
//                    }
					/**********/
					// 进行断线重新连接
					if (DXCL != null) {
						System.err.println("断线重新连接");
						try {
							Thread.sleep(100 + Util.random.nextInt(40) * 50);
						} catch (Exception e) {
							// TODO: handle exception
						}
						// 设置返回服务器的信息
						String serverMes = Agreement.getAgreement().enterGameAgreement(DXCL);
						channel.writeAndFlush(serverMes + "\n");
					}
				} else {
					futureListener.channel().eventLoop().schedule(new Runnable() {
						@Override
						public void run() {
							try {
								// 重连超过30次关闭游戏
								if (a <= 30) {
									a++;
									doConnect();
								} else {
									System.exit(0);
								}
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}, 10, TimeUnit.SECONDS);
				}
			}
		});
	}

	/**
	 * 服务器ip和端口类
	 *
	 * @throws Exception
	 */
	public static String[] getServerIpAndPort() throws Exception {
		Mac = getLocalMac();
		// 128位公钥
		String str = AESUtil.AESJDKDncode(CreateTextUtil.getContent("resource/other/opacity-inif.pat"),
				">LA~h4FNKPMJW077jxO");
		privateStr = AESUtil.AESJDKDncode(CreateTextUtil.getContent("resource/other/opacity-selfinif.pat"), str);
		String msg1 = AESUtil.AESJDKDncode(CreateTextUtil.getContent("resource/other/init.txt"), privateStr);
		String mes1[] = msg1.toString().split(";");
		int sum = Integer.parseInt(mes1[0].split("=")[1]);
		String portAndIp[] = new String[(sum) * 8];
		for (int i = 0; i < portAndIp.length; i++) {
			if (i + 1 < mes1.length) {
				portAndIp[i] = mes1[i + 1].split("=")[1];
			}
		}
		// for (int i = 0; i < 8; i++) {
		// portAndIp[portAndIp.length-8+i]=portAndIp[i];
		// }
		// portAndIp[portAndIp.length-8]="联赛区";
		// portAndIp[portAndIp.length-7]="103.27.6.34";
		// portAndIp[portAndIp.length-6]="7101";
		return portAndIp;
	}

	/** 转区格式 */
//	public static void ChangeServer(int i) {
//		String portAndIp[] = new String[8];
//		for (int j = 0; j < 8; j++) {
//			portAndIp[j] = potAndIpStrings[i * 8 + j];
//		}
//		potAndIpStrings = portAndIp;
//		int qid = Integer.parseInt(potAndIpStrings[5]);
//		if (qid >= 21300 && qid <= 21399) {
//			potAndIpStrings[1] = "125.77.188.182";
//		} else if ((qid >= 21200 && qid <= 21299) || (qid >= 21000 && qid <= 21099)) {
//			potAndIpStrings[1] = "125.77.188.182";
//		} else if ((qid >= 10000 && qid <= 21299)) {
//			potAndIpStrings[1] = "125.77.188.182";
//		} else if ((qid >= 21400 && qid <= 21499)) {
//			potAndIpStrings[1] = "110.43.196.183";
//		} else if ((qid >= 21500)) {
//			potAndIpStrings[1] = "218.244.156.173";
//		}
//	}

	/** 获取mac地址 */
	public static String getLocalMac() throws Exception {
		try {
			Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
			byte[] mac = null;
			while (allNetInterfaces.hasMoreElements()) {
				NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
				if (netInterface.isLoopback() || netInterface.isVirtual() || netInterface.isPointToPoint() || !netInterface.isUp()) {
					continue;
				} else {
					mac = netInterface.getHardwareAddress();
					if (mac != null) {
						StringBuilder sb = new StringBuilder();
						for (int i = 0; i < mac.length; i++) {
							sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
						}
						if (sb.length() > 0) {
							return sb.toString();
						}
					}
				}
			}
		} catch (Exception e) {
			//system.out.println("MAC地址获取失败");
		}
		return "";
	}

	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		GameClient.ip = ip;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		GameClient.port = port;
	}

}